import { useState, type HTMLAttributes } from "react";
import { Link, type LinkProps } from "react-router";
import clsm from "@/lib/utils/clsm";
import ModePopover from "./ModePopover";
import ProgramSettingDialog from "../ProgramSettingDialog";
import PlayIcon from "@/assets/icons/play.svg?jsx";
import FastForwardIcon from "@/assets/icons/fast-forward-circle.svg?jsx";
import RewindIcon from "@/assets/icons/rewind-circle.svg?jsx";
import SkipEndIcon from "@/assets/icons/skip-end-circle.svg?jsx";
import PauseIcon from "@/assets/icons/pause.svg?jsx";
import StopIcon from "@/assets/icons/stop-circle.svg?jsx";
import GridIcon from "@/assets/icons/grid.svg?jsx";
import InputModeIcon from "@/assets/images/input-mode.png?jsx";
import TransferDataIcon from "@/assets/images/transfer-data.png?jsx";
import PRGModeIcon from "@/assets/images/prg-mode.png?jsx";
import { useDeviceContext } from "@/providers/DeviceProvider";
import LoadingIcon from "@/assets/icons/loading-rotate-ring.svg?jsx";
import useFetch from "@/lib/hooks/useFetch";
import {
  continueDevice,
  keepDevice,
  nextStep,
  resetDeviceStatus,
  runDevice,
  stopDevice,
} from "@/lib/api/deviceStatus";
import { useAtomValue } from "jotai";
import { tokenAtom } from "@/store/user";
import { useMessage } from "@/providers/AntdMessageProvider";
import getRequestErrorMessage from "@/lib/utils/getRequestErrorMessage";
import ConstantSettingDialog from "../ConstantSettingDialog";
import JumpStepDialog from "./JumpStepDialog";
import { useModal } from "@/providers/AntdModalProvider";

export default function StatusControl() {
  const [showJumpStepDialog, setShowJumpStepDialog] = useState(false);
  const [showConstantSettingDialog, setShowConstantSettingDialog] =
    useState(false);
  const [showModePopover, setShowModePopover] = useState(false);
  const [showProgramDialog, setShowProgrmDialog] = useState(false);
  const { device, reloadDeviceList } = useDeviceContext();
  const token = useAtomValue(tokenAtom);
  const message = useMessage();

  function handleToggleConstantSettingDialog(visible: boolean) {
    setShowConstantSettingDialog(visible);
    if (visible) {
      setShowProgrmDialog(false);
      setShowModePopover(false);
    }
  }

  function handleToggleModePopover(visible: boolean) {
    setShowModePopover(visible);
    if (visible) {
      setShowProgrmDialog(false);
      setShowConstantSettingDialog(false);
    }
  }

  function handleToggleProgramDialog(visible: boolean) {
    setShowProgrmDialog(visible);
    if (visible) {
      setShowModePopover(false);
      setShowConstantSettingDialog(false);
    }
  }

  const { isLoading: isResetLoading, refetch: handleResetDeviceStatus } =
    useFetch({
      fetchFn: () =>
        resetDeviceStatus(device!.deviceId, token).then((res) => {
          if (res.code !== 200) {
            throw res;
          }
        }),
      onError(error) {
        message.error(getRequestErrorMessage(error, "操作失败"));
      },
      onSuccess() {
        message.success("操作成功");
        reloadDeviceList();
      },
    });

  const { isLoading: isRunLoading, refetch: handleRunDevice } = useFetch({
    fetchFn: () =>
      runDevice(device!.deviceId, token).then((res) => {
        if (res.code !== 200) {
          throw res;
        }
      }),
    onError(error) {
      message.error(getRequestErrorMessage(error, "操作失败"));
    },
    onSuccess() {
      message.success("操作成功");
      reloadDeviceList();
    },
  });

  const { isLoading: isKeepLoading, refetch: handleKeepDevice } = useFetch({
    fetchFn: () =>
      keepDevice(device!.deviceId, token).then((res) => {
        if (res.code !== 200) {
          throw res;
        }
      }),
    onError(error) {
      message.error(getRequestErrorMessage(error, "操作失败"));
    },
    onSuccess() {
      message.success("操作成功");
      reloadDeviceList();
    },
  });
  const { isLoading: isStopLoading, refetch: handleStopDevice } = useFetch({
    fetchFn: () =>
      stopDevice(device!.deviceId, token).then((res) => {
        if (res.code !== 200) {
          throw res;
        }
      }),
    onError(error) {
      message.error(getRequestErrorMessage(error, "操作失败"));
    },
    onSuccess() {
      message.success("操作成功");
      reloadDeviceList();
    },
  });

  const { isLoading: isNextStepLoading, refetch: handleNextStep } = useFetch({
    fetchFn: () =>
      nextStep(device!.deviceId, token).then((res) => {
        if (res.code !== 200) {
          throw res;
        }
      }),
    onError(error) {
      message.error(getRequestErrorMessage(error, "操作失败"));
    },
    onSuccess() {
      message.success("操作成功");
      reloadDeviceList();
    },
  });

  const { isLoading: isContinueLoading, refetch: handleContinue } = useFetch({
    fetchFn: () =>
      continueDevice(device!.deviceId, token).then((res) => {
        if (res.code !== 200) {
          throw res;
        }
      }),
    onError(error) {
      message.error(getRequestErrorMessage(error, "操作失败"));
    },
    onSuccess() {
      message.success("操作成功");
      reloadDeviceList();
    },
  });

  return (
    <div className="relative flex h-16 flex-none items-center dark:bg-black">
      {device!.conn && !device!.deviceControl && (
        <div className="flex flex-none basis-1/3 justify-center gap-x-4 px-4">
          <Button
            label="参数复位"
            loading={isResetLoading}
            onClick={handleResetDeviceStatus}
            disabled={device!.deviceStatus !== "1"}
            confirm="确定执行参数复位操作吗？"
          >
            <RewindIcon height={30} width={30} />
          </Button>
          <Button
            label="开机"
            loading={isRunLoading}
            onClick={handleRunDevice}
            disabled={device!.deviceStatus !== "1"}
            confirm="确定执行开机操作吗？"
          >
            <PlayIcon height={30} width={30} />
          </Button>
          <Button
            label="继续"
            loading={isContinueLoading}
            onClick={handleContinue}
            disabled={device!.deviceStatus !== "3"}
            confirm="确定执行继续操作吗？"
          >
            <PlayIcon height={30} width={30} />
          </Button>
          <Button
            label="保持"
            loading={isKeepLoading}
            onClick={handleKeepDevice}
            disabled={device!.deviceStatus !== "2"}
            confirm="确定执行保持操作吗？"
          >
            <PauseIcon height={30} width={30} />
          </Button>
          <Button
            label="停机"
            loading={isStopLoading}
            onClick={handleStopDevice}
            disabled={device!.deviceStatus === "1"}
            confirm="确定执行停机操作吗？"
          >
            <StopIcon height={30} width={30} />
          </Button>
          <Button
            label="下一步"
            loading={isNextStepLoading}
            onClick={handleNextStep}
            disabled={device!.mode === "fix"}
            confirm="确定执行下一步操作吗？"
          >
            <SkipEndIcon height={30} width={30} />
          </Button>
          <Button
            label="跳步到..."
            onClick={() => setShowJumpStepDialog(true)}
            disabled={device!.mode === "fix"}
            confirm="确定执行跳步操作吗？"
          >
            <FastForwardIcon height={30} width={30} />
          </Button>
        </div>
      )}
      <div className="absolute left-1/2 flex h-full -translate-x-1/2 items-center *:h-full *:px-2">
        <Button
          label="定值"
          onClick={() => handleToggleConstantSettingDialog(true)}
          className="group"
        >
          <InputModeIcon
            className={clsm(
              "size-8 brightness-50 group-hover:brightness-100",
              device!.mode === "fix" && "brightness-100",
            )}
          />
        </Button>
        <Button
          data-mode-popover-control
          onClick={() => setShowModePopover(!showModePopover)}
          label="模式"
          disabled={device!.deviceStatus !== "1"}
        >
          <TransferDataIcon className="size-8 brightness-50 hover:brightness-100" />
        </Button>
        <Button
          label="程序"
          onClick={() => handleToggleProgramDialog(true)}
          className="group"
        >
          <PRGModeIcon
            className={clsm(
              "size-8 brightness-50 group-hover:brightness-100",
              device!.mode === "program" && "brightness-100",
            )}
          />
        </Button>
      </div>
      <div className="ml-auto mr-6 flex gap-x-4">
        {/* <Button label="报警复位">
          <AlarmIcon className="size-8" />
        </Button> */}
        <Button link to="/device" label="设备列表">
          <GridIcon height={30} width={30} />
        </Button>
      </div>
      <JumpStepDialog
        deviceId={device!.deviceId}
        visible={showJumpStepDialog}
        onClose={() => setShowJumpStepDialog(false)}
        onSuccess={reloadDeviceList}
      />
      <ConstantSettingDialog
        device={device!}
        visible={showConstantSettingDialog}
        onClose={() => handleToggleConstantSettingDialog(false)}
      />
      <ModePopover
        visible={showModePopover}
        onVisibleChange={handleToggleModePopover}
      />
      <ProgramSettingDialog
        visible={showProgramDialog}
        onVisibleChange={handleToggleProgramDialog}
      />
    </div>
  );
}

type ButtonProps = HTMLAttributes<HTMLButtonElement> & {
  confirm?: string;
};
type LinkButtonProps = LinkProps & { link: true };

function isLink(p: ButtonProps | LinkButtonProps): p is LinkButtonProps {
  return "link" in p && p.link;
}

function Button(
  props: (ButtonProps | LinkButtonProps) & {
    label: string;
    disabled?: boolean;
    loading?: boolean;
  },
) {
  const { children, className, label, disabled, loading, onClick, ...rest } =
    props;

  const modal = useModal();

  if (disabled) {
    return null;
  }

  const content = (
    <>
      <span className="flex size-[30px] items-center justify-center">
        {loading ? <LoadingIcon height={20} width={20} /> : children}
      </span>
      <span className="mt-1 text-sm">{label || <>&nbsp;</>}</span>
    </>
  );
  const classes = clsm("flex justify-center flex-col items-center", className);

  if (isLink(rest)) {
    const { link, ..._ } = rest;
    return (
      <Link
        className={classes}
        onClick={loading ? undefined : (onClick as LinkProps["onClick"])}
        {..._}
      >
        {content}
      </Link>
    );
  }

  const { confirm, ..._ } = rest as ButtonProps;

  if (confirm) {
    return (
      <button
        className={classes}
        onClick={(e) => {
          modal.confirm({
            content: confirm,
            onOk: () => (onClick as ButtonProps["onClick"])?.(e),
            centered: true,
          });
        }}
        {..._}
      >
        {content}
      </button>
    );
  }

  return (
    <button
      className={classes}
      onClick={loading ? undefined : (onClick as ButtonProps["onClick"])}
      {..._}
    >
      {content}
    </button>
  );
}
